"""
安全管理器 - 处理敏感信息和密码管理
"""

import os
import base64
import hashlib
import secrets
from typing import Optional, Dict, Any, Tuple
from pathlib import Path
import json

from logger_manager import get_logger
from exceptions import AuthenticationError, ConfigError


class SecurityManager:
    """安全管理器"""
    
    def __init__(self, config_dir: str = "secure_config"):
        """初始化安全管理器
        
        Args:
            config_dir: 安全配置目录
        """
        self.logger = get_logger("security")
        self.config_dir = Path(config_dir)
        self.config_dir.mkdir(exist_ok=True)
        
        # 密钥文件路径
        self.key_file = self.config_dir / ".app_key"
        self.secure_config_file = self.config_dir / "secure.json"
        
        # 初始化或加载密钥
        self.key = self._load_or_create_key()
    
    def _load_or_create_key(self) -> bytes:
        """加载或创建加密密钥"""
        try:
            if self.key_file.exists():
                # 从文件加载密钥
                with open(self.key_file, 'rb') as f:
                    key = f.read()
                self.logger.debug("加载现有密钥")
                return key
            else:
                # 创建新密钥
                key = secrets.token_bytes(32)  # 256位密钥
                with open(self.key_file, 'wb') as f:
                    f.write(key)
                
                # 设置文件权限（仅所有者可读写）
                if os.name != 'nt':  # 非Windows系统
                    os.chmod(self.key_file, 0o600)
                
                self.logger.info("创建新的加密密钥")
                return key
                
        except Exception as e:
            self.logger.error(f"密钥管理失败: {e}")
            raise ConfigError(f"密钥管理失败: {e}")
    
    def _simple_encrypt(self, data: str) -> str:
        """简单加密（基于XOR和Base64）"""
        try:
            # 将字符串转换为字节
            data_bytes = data.encode('utf-8')
            
            # 使用密钥进行XOR加密
            encrypted_bytes = bytearray()
            for i, byte in enumerate(data_bytes):
                key_byte = self.key[i % len(self.key)]
                encrypted_bytes.append(byte ^ key_byte)
            
            # Base64编码
            encrypted_b64 = base64.b64encode(encrypted_bytes).decode('utf-8')
            return encrypted_b64
            
        except Exception as e:
            self.logger.error(f"加密失败: {e}")
            raise AuthenticationError(f"加密失败: {e}")
    
    def _simple_decrypt(self, encrypted_data: str) -> str:
        """简单解密"""
        try:
            # Base64解码
            encrypted_bytes = base64.b64decode(encrypted_data.encode('utf-8'))
            
            # 使用密钥进行XOR解密
            decrypted_bytes = bytearray()
            for i, byte in enumerate(encrypted_bytes):
                key_byte = self.key[i % len(self.key)]
                decrypted_bytes.append(byte ^ key_byte)
            
            # 转换为字符串
            decrypted_str = decrypted_bytes.decode('utf-8')
            return decrypted_str
            
        except Exception as e:
            self.logger.error(f"解密失败: {e}")
            raise AuthenticationError(f"解密失败: {e}")
    
    def store_password(self, identifier: str, password: str) -> bool:
        """存储加密密码
        
        Args:
            identifier: 密码标识符
            password: 明文密码
            
        Returns:
            是否存储成功
        """
        try:
            # 加密密码
            encrypted_password = self._simple_encrypt(password)
            
            # 加载现有配置
            secure_config = self._load_secure_config()
            
            # 存储加密密码
            secure_config['passwords'] = secure_config.get('passwords', {})
            secure_config['passwords'][identifier] = encrypted_password
            
            # 保存配置
            success = self._save_secure_config(secure_config)
            
            if success:
                self.logger.info(f"密码已存储: {identifier}")
            else:
                self.logger.error(f"密码存储失败: {identifier}")
            
            return success
            
        except Exception as e:
            self.logger.error(f"存储密码失败: {e}")
            return False
    
    def get_password(self, identifier: str) -> Optional[str]:
        """获取解密密码
        
        Args:
            identifier: 密码标识符
            
        Returns:
            明文密码，如果不存在返回None
        """
        try:
            # 加载配置
            secure_config = self._load_secure_config()
            
            # 获取加密密码
            passwords = secure_config.get('passwords', {})
            encrypted_password = passwords.get(identifier)
            
            if not encrypted_password:
                return None
            
            # 解密密码
            password = self._simple_decrypt(encrypted_password)
            self.logger.debug(f"获取密码: {identifier}")
            
            return password
            
        except Exception as e:
            self.logger.error(f"获取密码失败: {e}")
            return None
    
    def remove_password(self, identifier: str) -> bool:
        """删除存储的密码
        
        Args:
            identifier: 密码标识符
            
        Returns:
            是否删除成功
        """
        try:
            # 加载配置
            secure_config = self._load_secure_config()
            
            # 删除密码
            passwords = secure_config.get('passwords', {})
            if identifier in passwords:
                del passwords[identifier]
                
                # 保存配置
                success = self._save_secure_config(secure_config)
                
                if success:
                    self.logger.info(f"密码已删除: {identifier}")
                
                return success
            else:
                self.logger.warning(f"密码不存在: {identifier}")
                return True
                
        except Exception as e:
            self.logger.error(f"删除密码失败: {e}")
            return False
    
    def _load_secure_config(self) -> Dict[str, Any]:
        """加载安全配置"""
        try:
            if self.secure_config_file.exists():
                with open(self.secure_config_file, 'r', encoding='utf-8') as f:
                    return json.load(f)
            return {}
        except Exception as e:
            self.logger.warning(f"加载安全配置失败: {e}")
            return {}
    
    def _save_secure_config(self, config: Dict[str, Any]) -> bool:
        """保存安全配置"""
        try:
            with open(self.secure_config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
            
            # 设置文件权限
            if os.name != 'nt':  # 非Windows系统
                os.chmod(self.secure_config_file, 0o600)
            
            return True
        except Exception as e:
            self.logger.error(f"保存安全配置失败: {e}")
            return False
    
    def hash_password(self, password: str, salt: Optional[str] = None) -> Tuple[str, str]:
        """哈希密码
        
        Args:
            password: 明文密码
            salt: 盐值，如果为None则生成新的
            
        Returns:
            (哈希值, 盐值)
        """
        if salt is None:
            salt = secrets.token_hex(16)
        
        # 使用PBKDF2进行哈希
        password_hash = hashlib.pbkdf2_hmac(
            'sha256',
            password.encode('utf-8'),
            salt.encode('utf-8'),
            100000  # 迭代次数
        )
        
        return password_hash.hex(), salt
    
    def verify_password(self, password: str, password_hash: str, salt: str) -> bool:
        """验证密码
        
        Args:
            password: 明文密码
            password_hash: 存储的哈希值
            salt: 盐值
            
        Returns:
            密码是否正确
        """
        computed_hash, _ = self.hash_password(password, salt)
        return computed_hash == password_hash
    
    def get_env_or_stored_password(self, identifier: str, env_var: str = None) -> Optional[str]:
        """从环境变量或存储中获取密码
        
        Args:
            identifier: 密码标识符
            env_var: 环境变量名
            
        Returns:
            密码，优先使用环境变量
        """
        # 优先使用环境变量
        if env_var:
            env_password = os.getenv(env_var)
            if env_password:
                self.logger.debug(f"从环境变量获取密码: {env_var}")
                return env_password
        
        # 从存储中获取
        stored_password = self.get_password(identifier)
        if stored_password:
            self.logger.debug(f"从存储获取密码: {identifier}")
            return stored_password
        
        self.logger.warning(f"未找到密码: {identifier}")
        return None


# 全局安全管理器实例
security_manager = SecurityManager()


# 便捷函数
def store_password(identifier: str, password: str) -> bool:
    """存储密码的便捷函数"""
    return security_manager.store_password(identifier, password)


def get_password(identifier: str, env_var: str = None) -> Optional[str]:
    """获取密码的便捷函数"""
    return security_manager.get_env_or_stored_password(identifier, env_var)


def remove_password(identifier: str) -> bool:
    """删除密码的便捷函数"""
    return security_manager.remove_password(identifier)
